<?php


namespace App\Http\Controllers\Api;


use App\Jobs\Shop\ShopOrderDeliverInfoManage;
use App\Jobs\System\CheckBatchCahceDataLossJob;
use App\Lib\ApplePay\ApplePay;
use App\Lib\WeApp\WeApp;
use App\Models\Bureau\WxClubTeam;
use App\Models\Shop\WxShopGoods;
use App\Models\Shop\WxShopGoodsProduct;
use App\Models\Shop\WxShopOrderGoods;
use App\Models\Used\WxUsedGood;
use App\Models\WxDomainAuth;
use App\Models\WxRefund;
use App\Wen\Utils\FieldUtils;
use App\Wen\Utils\OrderUtils;
use App\Wen\Utils\Settings;
use App\Wen\Utils\ShopUtils;
use App\Wen\Utils\UserUtils;
use App\Wen\Utils\Utils;
use App\Lib\Pay\EPay;
use App\Models\Shop\WxShopOrder;
use App\Models\WxOrder;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Yansongda\Pay\Pay;

class NotifyController extends BaseController
{

    /**
     * @param $event_type 退款状态 REFUND.SUCCESS 退款成功通知 REFUND.ABNORMAL 退款异常通知 REFUND.CLOSED 退款关闭通知
     * @param $out_refund_no 自己的退款单号
     * @param $transaction_id 退款的流水号
     * @param $refund_time 推荐完成时间
     * @param $refund_amount 退款金额
     * @param $refund_account 退款账号说明
     * @param $refund_from 0：微信 1：支付宝
     */
    private function _refund($event_type, $out_refund_no, $transaction_id, $refund_time, $refund_amount, $refund_account, $refund_from){
        $order_good = WxShopOrderGoods::where('refund_no', $out_refund_no)->first();
        if($order_good){
            if($order_good->state == 3){
                // 已退款
                return true;
            }
            if($order_good->recharge > 0){
                DB::beginTransaction();
                try {
                    // todo:
                    $shop_order = WxShopOrder::where('id', $order_good->order_id)->first();
                    $updated_at = Carbon::now();
                    $nr = '您购买的：「' . $order_good->name . '(规格：' . $order_good->product . ')」×' . $order_good->quantity . '件的退款申请已处理完毕';
                    // 退款记录
                    $refund_record = new WxRefund();
                    $refund_record->user_id = $order_good->buyer_user_id;
                    $refund_record->order_good_id = $order_good->id;
                    $refund_record->order_id = $order_good->order_id;
                    $refund_record->goods_id = $order_good->goods_id;
                    $refund_record->product_id = $order_good->product_id;
                    $refund_record->amount = $order_good->recharge;
                    $refund_record->goods_type = $order_good->goods_type;
                    $refund_record->save();

                    if($event_type == 'REFUND.SUCCESS'){
                        WxShopOrderGoods::where('id', $order_good->id)->update([
                            'refund_no' => $out_refund_no,
                            'state' => 3,
                            'refund_from' => $refund_from,
                            'refund_amount' => $refund_amount,
                            'refund_time' => $refund_time,
                            'refund_account' => $refund_account
                        ]);
                    }else if($event_type == 'REFUND.ABNORMAL' || $event_type == 'REFUND.CLOSED'){
                        WxShopOrderGoods::where('id', $order_good->id)->update([
                            'state' => 3,
                            'updated_at' => $updated_at
                        ]);
                        $financial_type = 3;
                        if($order_good->goods_type == 7){
                            $financial_type = 29;
                        }
                        if($shop_order->serial_number){
                            UserUtils::update_user_financial($order_good->buyer_user_id,$financial_type, $order_good->recharge,
                                '您收到了一笔来自「' . $order_good->name . '(规格：' . $order_good->product . ')」×' . $order_good->quantity . '件的退款，退款金额¥' . $order_good->recharge
                            );
                        }
                    }else{
                        return false;
                    }
                    UserUtils::add_user_notice(6002, $order_good->buyer_user_id, '商品退款通知', $nr, 100);

                    $result_ = DB::table('wx_shop_order_goods as wg')
                        ->select(DB::raw('COUNT(*) as total_count, SUM(CASE WHEN state = 3 THEN 1 ELSE 0 END) as state_3_count'))
                        ->where('wg.order_id', $order_good->id)
                        ->first();

                    if ($result_->total_count == $result_->state_3_count) {
                        WxShopOrder::where('id', $order_good->order_id)->update([
                            'pay_status' => 3,
                            'status' => 4,
                            'updated_at' => $updated_at
                        ]);
                    }

                    if(in_array($order_good->goods_type, FieldUtils::getShopGoodTypes())){
                        WxShopGoods::where('id', $order_good->goods_id)->decrement('buys', (int)($order_good->quantity));
                        WxShopGoodsProduct::where('id', $order_good->product_id)->increment('stock', (int)($order_good->quantity));
                    }else{
                        if($order_good->goods_type == 6){
                            WxUsedGood::where('id', $order_good->goods_id)->update([
                                'status' => 6
                            ]);
                        }else if($order_good->goods_type == 7){
                            $team = WxClubTeam::find($order_good->product_id);
                            if ($team) {
                                $members_arr = $team->members; // 获取当前成员数组
                                if($members_arr){
                                    $key = array_search((int)$order_good->buyer_user_id, $members_arr);
                                    if ($key !== false) {
                                        unset($members_arr[$key]);
                                        // 设置并保存成员数组，确保触发属性修改器和事件
                                        $members = array_unique($members_arr);
                                        $team->members = $members;
                                        $team->members_num = count($members);
                                        $team->save();
                                        Cache::forget('get_join_info:'.$team->bureau_id.':'.$order_good->buyer_user_id);
                                        Cache::forget('bureau:avatars:'.$team->bureau_id);
                                    }
                                }
                            }
                        }
                    }
                    DB::commit();
                    return true;
                } catch (\Exception $e) {
                    DB::rollBack();
                    _logger_(__file__, __line__, $e->getMessage());
                    return false;
                }
            }
        }
    }

    /**
     * 所有支付的 处理支付通知 函数
     * @param $out_trade_no
     * @param $transaction_id
     * @param $payment_time
     * @param $payed
     * @param $which_pay 0:微信 1：支付宝 2：易支付 3:苹果
     */
    private function _notify($out_trade_no, $transaction_id, $payment_time, $payed, $which_pay = 0){
        try {
            // 判断订单是 来自商品 还是 来自充电或者开通会员。
            $WxOrder = WxOrder::where('order_number', $out_trade_no)->first();
            if ($WxOrder) {
                // 处理重复通知
                if(in_array($WxOrder->order_state, [1, 3, 4, 5, 6])){
                    return true;
                }

                // 先检查是否需要微信发货管理
                $is_need_deliver_info_manage = false;
                if($WxOrder->order_serial_platform === 0 && $WxOrder->order_serial_platform_type == 'mini'){
                    if(Settings::get('need_mini_deliver_info_manage', 0) == 1){
                        $is_need_deliver_info_manage = true;
                    }
                }

                if($is_need_deliver_info_manage){
                    if($which_pay != $WxOrder->order_serial_platform){
                        _logger_(__file__, __line__, '理论上不应出现这种情况,order_id:'.$WxOrder->id);
                    }
                    WxOrder::where('order_number', $out_trade_no)->update(['order_state' => 3, 'order_serial_number' => $transaction_id]);
                    $WxOrder->order_serial_number = $transaction_id;
                    // 尝试通知
                    $weapp = new WeApp('mini');
                    $manage = $weapp->getDeliverInfoManage();
                    $manage->virtualDeliverOrder($WxOrder);
                }else{
                    WxOrder::where('order_number', $out_trade_no)->update(['order_state' => 1, 'order_serial_number' => $transaction_id, 'order_serial_platform'=>$which_pay]);
                    OrderUtils::order_obtains($WxOrder, $which_pay);
                }
            } else {

                // 处理重复通知
                if(WxShopOrder::where('order_id', $out_trade_no)->whereIn('pay_status', [2])->exists()){
                    return true;
                }

                $WxShopOrder = WxShopOrder::where('order_id', $out_trade_no)->first();
                if($WxShopOrder){
                    //SHOP
                    $discounts_amount = $WxShopOrder->discounts_amount;
                    $pay_way = ShopUtils::generate_payway_text($discounts_amount,0, $which_pay === 0 ? $payed : 0,
                        $which_pay === 1 ? $payed : 0, 0, $WxShopOrder->coins_num, $which_pay === 3 ? $payed : 0,
                        $which_pay === 2 ? $payed : 0);

                    WxShopOrder::where('id', $WxShopOrder->id)
                        ->update(['pay_status' => 2, 'status' => 1, 'serial_number' => $transaction_id, 'serial_platform'=>$which_pay, 'payment_time' => $payment_time, 'payed' => $payed, 'pay_way'=>$pay_way]);

                    $this->usedGoodPaied($WxShopOrder->id);
                    $this->bureauGoodPaied($WxShopOrder->id);


                    $is_need_deliver_info_manage = false;
                    if($WxShopOrder->serial_platform === 0 && $WxShopOrder->serial_platform_type == 'mini'){
                        if(Settings::get('need_mini_deliver_info_manage', 0) == 1){
                            if(WxShopOrderGoods::where('order_id', $WxShopOrder->id)->whereIn('goods_type', [2,3,4])->where('state', 0)->exists()){
                                $is_need_deliver_info_manage = true;
                            }
                        }
                    }

                    if(!$is_need_deliver_info_manage){
                        ShopUtils::paied_content_process($WxShopOrder->id);
                    }

                    ShopUtils::split_shop_order_by_seller($WxShopOrder->id);
                    ShopUtils::split_shop_order_by_type($WxShopOrder->id);
                    ShopUtils::order_buys_and_stock($WxShopOrder->id);

                    if($is_need_deliver_info_manage){
                        WxShopOrder::withTrashed()->where('id', $WxShopOrder->id)->orWhere('parent_order_id', $WxShopOrder->id)->update([
                            'status' => 9
                        ]);
                        ShopOrderDeliverInfoManage::dispatch('virtual-upload', $WxShopOrder->id, null);
                    }

                    UserUtils::assistant_notice('admin', '您的商城有新的订单。');

                }else{
                    return false;
                }

            }

            return true;
        } catch (\Exception $e) {
            _logger_(__file__, __line__, $e->getMessage());
            return false;
        }
    }

    public function usedGoodPaied($order_id){

        $goods_ids = [];
        WxShopOrderGoods::where('order_id', $order_id)->where('goods_type', 6)->get(['goods_id'])->map(function ($v) use (&$goods_ids){
            $goods_ids[] = $v->goods_id;
            return $v;
        });

        if($goods_ids){
            foreach ($goods_ids as $used_id){
                WxUsedGood::where('id', $used_id)->update([
                    'status' => 5
                ]);
            }
        }
    }

    public function bureauGoodPaied($order_id){
        WxShopOrderGoods::where('order_id', $order_id)->where('goods_type', 7)->get(['buyer_user_id','goods_id', 'product_id'])->map(function ($v){
            $team = WxClubTeam::find($v->product_id);
            if ($team) {
                $members_arr = $team->members; // 获取当前成员数组
                $members_arr[] = (int)$v->buyer_user_id; // 添加新的成员ID
                // 设置并保存成员数组，确保触发属性修改器和事件
                $members = array_unique($members_arr);
                $team->members = $members;
                $team->members_num = count($members);
                $team->save();
                Cache::forget('get_join_info:'.$team->bureau_id.':'.$v->buyer_user_id);
                Cache::forget('bureau:avatars:'.$team->bureau_id);
            }
        });
    }

    /**
     * 微信app支付通知
     */
    public function wechat_app(){

        $config = json_decode(Cache::get('app_pay_config'), true);
        if(_empty_($config)){
            CheckBatchCahceDataLossJob::dispatch();
        }
        Pay::config($config);

        $result = Pay::wechat()->callback();
        if($result){
            if($result->event_type == 'TRANSACTION.SUCCESS'){
                $out_trade_no = $result->resource['ciphertext']['out_trade_no'];
                $transaction_id = $result->resource['ciphertext']['transaction_id'];
                $payment_time = Utils::strTimeFormat($result->resource['ciphertext']['success_time']);//支付回调支付时间
                $total_fee = $result->resource['ciphertext']['amount']['total'];
                $payed = $total_fee / 100;

                if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 0)){
                    return Pay::wechat()->success();
                }
            }else if($result->event_type == 'REFUND.SUCCESS' || $result->event_type == 'REFUND.ABNORMAL' || $result->event_type == 'REFUND.CLOSED'){
                $event_type = $result->event_type;
                $out_refund_no = $result->resource['ciphertext']['out_refund_no'];
                $transaction_id = $result->resource['ciphertext']['transaction_id'];
                $refund_time = Utils::strTimeFormat($result->resource['ciphertext']['success_time']);//支付回调支付时间
                $user_received_account = $result->resource['ciphertext']['user_received_account'];
                $refund_fee = $result->resource['ciphertext']['amount']['refund'];
                $refund = $refund_fee / 100;

                if($this->_refund($event_type, $out_refund_no, $transaction_id, $refund_time, $refund, $user_received_account, 0)){
                    return Pay::wechat()->success();
                }
            }
        }
    }

    /**
     * 苹果支付 通知url
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function apple_app(Request $request){
        $orderId = $request->orderId;
        $productId = $request->productid;
        $user_id = $request->username;
        $transaction = $request->transaction;
        $restore = (int)($request->restore ?? 0);

        _logger_(__file__, __line__, $transaction);

        if($restore == 1){
            if(_empty_($transaction)){
                return $this->fail(200001);
            }
        }else{
            if(_empty_($orderId) || _empty_($productId) || _empty_($user_id) || _empty_($transaction)){
                return $this->fail(200001);
            }
        }


        if( _empty_(_array_key($transaction, 'transactionDate', '')) ||
            _empty_(_array_key($transaction, 'transactionIdentifier', '')) ||
            _empty_(_array_key($transaction, 'transactionState', '')) ||
            _empty_(_array_key($transaction, 'transactionReceipt', ''))
        ){
            return $this->fail(200001);
        }

        if($restore === 0){
            Cache::put('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', ''), json_encode(['orderId'=>$orderId, 'user_id'=>$user_id, 'productid'=>$productId]), 3600 * 24);
        }else{
            if(Cache::has('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', ''))){
                $cache_data = Cache::get('transactionIdentifier:'._array_key($transaction, 'transactionIdentifier', '') );
                if($cache_data){
                    $cache_data = json_decode($cache_data, true);
                    $orderId = $cache_data['orderId'];
                    $productId = $cache_data['productid'];
                    $user_id = $cache_data['user_id'];
                }
            }
            if(_empty_($orderId) || _empty_($productId)){
                return $this->fail(200001);
            }
        }

        $is_shop_order = false;
        $order = null;

        $notify_data = [

        ];

        if(strpos($productId, 'apple_pay_product_recharge') === 0){
            $productid_num = (int)(str_replace('apple_pay_product_recharge_', '', $productId));
            $order = WxOrder::find($orderId);
            $notify_data['type'] = 3;
            $notify_data['num'] = $productid_num;
        }else if(strpos($productId, 'apple_pay_product_vip') === 0){
            $product_price = (int)(str_replace('apple_pay_product_vip_', '', $productId));
            $order = WxOrder::find($orderId);
            $notify_data['type'] = 1;
            $notify_data['price'] = $product_price;
        }

        if(_empty_($order)){
            return $this->fail(200004, [], '没有与此orderId对应的订单');
        }

        // 已经处理过的订单
        if($is_shop_order){
            if($order->pay_status != 1){
                return $this->fail(200010, [], '该订单已经通知过');
            }
        }else{
            if($order->order_state != 0){
                return $this->fail(200010, [], '该订单已经通知过');
            }
        }
        $is_sand_box = false;
        $applePay = new ApplePay(_array_key($transaction, 'transactionReceipt', ''), Settings::get('apple_pay_password', ''));
        if ($applePay->verifyReceipt($is_sand_box)) {
            $result = $applePay->query($productId, function ($tradeNo, $returnData) use ($order, $is_shop_order, $notify_data) {
//                _logger_(__file__, __line__, $returnData);
                if($is_shop_order){

                }else{
                    if($notify_data['type'] == 1){
                        return $this->_notify($order->order_number, $tradeNo, current_time(), 0, 3);
                    }else if($notify_data['type'] == 3){
                        return $this->_notify($order->order_number, $tradeNo, current_time(), 0, 3);
                    }
                }

            });
            if ($result) {
                return $this->success();
            } else {
                return $this->fail(200004, [], $applePay->getError());
            }
        } else {
            return $this->fail(200004, [], $applePay->getError());
        }

    }

    public function alipay_app(){

        $config = json_decode(Cache::get('app_pay_config'), true);
        if(_empty_($config)){
            CheckBatchCahceDataLossJob::dispatch();
        }
        Pay::config($config);
        $result = Pay::alipay()->callback();

        // 否则当支付处理
        if($result->alipay_trade_app_pay_response){
            $result = $result->alipay_trade_app_pay_response;
        }
        if($result->trade_status == 'TRADE_SUCCESS' || $result->code == 10000){
            $out_trade_no = $result->out_trade_no;
            $transaction_id = $result->trade_no;
            $payment_time = $result->timestamp;//支付回调支付时间
            $payed = $result->total_amount;

            if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 1)){
                return Pay::alipay()->success();
            }
        }

    }

    public function alipay_wap(){

        $config = json_decode(Cache::get('app_pay_config'), true);
        if(_empty_($config)){
            CheckBatchCahceDataLossJob::dispatch();
        }
        Pay::config($config);
        $result = Pay::alipay()->callback();
        _logger_(__file__, __line__, $result);

        if($result->alipay_trade_wap_pay_response){
            $result = $result->alipay_trade_wap_pay_response;
        }
        if($result->trade_status == 'TRADE_SUCCESS' || $result->code == 10000){
            $out_trade_no = $result->out_trade_no;
            $transaction_id = $result->trade_no;
            $payment_time = $result->timestamp;//支付回调支付时间
            $payed = $result->total_amount;

            if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 1)){
                return Pay::alipay()->success();
            }
        }

    }

    public function yi_app(Request $request){
        if(_empty_($request->out_trade_no) || _empty_($request->sign)){
            return '';
        }

        $epay_config = json_decode(Cache::get('yi_pay_config'), true);
        if(_empty_($epay_config)){
            CheckBatchCahceDataLossJob::dispatch();
        }

        $epay = new EPay();
        $epay->key($epay_config['app_secret']);
//签名验证
        $data = $request->input();
        if(!$epay->signVerify($data)){
            exit();
        }

// 交易状态## 交易成功
        if($data['trade_status']=='TRADE_SUCCESS'){
            $out_trade_no=$data['out_trade_no'];//网站自己生成的订单号
            $transaction_id=$data['trade_no'];//第三方平台产生的订单号
            $total_fee=$data['money'];//金额
            $payment_time = date('Y-m-d H:i:s', time());
            $payed=(float)$total_fee;

            if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 2)){
                echo "success";
            }
        }
        return '';
    }


    /** 微信支付v2版本通知url
     * @return string
     */
    public function index()
    {
        $xml = file_get_contents('php://input');
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $valArr = json_decode(json_encode($xmlstring), true);

        $out_trade_no = $valArr['out_trade_no'];//支付回调订单号
        $transaction_id = $valArr['transaction_id'];//支付回调支付号
        $time_end = $valArr['time_end'];//支付回调支付时间
        $payment_time = date('Y-m-d H:i:s', strtotime($time_end));
        $total_fee = $valArr['total_fee'];//支付回调支付金额
        $payed = $total_fee / 100;

        if (_empty_($out_trade_no)) {
            die('错误');
        }
        _logger_(__file__, __line__, $out_trade_no.'开始处理微信小程序支付通知');
        if($this->_notify($out_trade_no, $transaction_id, $payment_time, $payed, 0)){
            return $this->successXml();
        }
    }




    private function successXml()
    {
        $arr = ['return_code' => 'SUCCESS', 'return_msg' => 'OK'];
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

}
